8.2 选择排序

选择排序是一种简单直观的排序算法。其基本思想是在未排序序列中找到最小(或最大)的元素,并将其与未排序序列的第一个元素交换,随后再继续从剩下的未排序序列中找最小(或最大)的元素,重复此操作直到序列有序。

本节代码存放目录为 lesson17


概念与原理

选择排序的原理如下:

  • 从未排序序列中找到最小的元素,放到已排序序列的末尾。

  • 再从剩下的未排序序列中找到最小的元素,继续放到已排序序列末尾。

  • 重复以上步骤,直到所有元素都放入已排序序列。

选择排序的基本特点:

  • 时间复杂度为 O(n^2),无论数组是否有序,每次都需要遍历整个未排序部分。

  • 选择排序是不稳定的,因为交换操作可能改变相同元素的相对顺序。


选择排序的步骤示例

给定如下无序数组,按照从小到大排序:

[5, 3, 8, 4, 2]

通过选择排序的步骤如下:

第一轮:

- 从 [5, 3, 8, 4, 2] 中找到最小值 2,交换 arr[0] 和 arr[4]

- 结果:[2, 3, 8, 4, 5]

第二轮:

- 从 [3, 8, 4, 5] 中找到最小值 3,不需要交换

- 结果:[2, 3, 8, 4, 5]

第三轮:

- 从 [8, 4, 5] 中找到最小值 4,交换 arr[2] 和 arr[3]

- 结果:[2, 3, 4, 8, 5]

第四轮:

- 从 [8, 5] 中找到最小值 5,交换 arr[3] 和 arr[4]

- 结果:[2, 3, 4, 5, 8]

最终,排序结果为 [2, 3, 4, 5, 8]


选择排序的时间复杂度

选择排序无论数组的初始状态如何,总是执行 n(n-1)/2 次比较。因此时间复杂度如下:

  • 最坏情况O(n²)

  • 最好情况O(n²)

  • 平均情况O(n²)

选择排序的特点是它总是进行固定数量的比较和交换,无论数组是否已经部分有序。

Go语言的实现

实现代码如下:

func selectionSort(arr []int) {
    length := len(arr)
    num := 0

    // 轮次控制
    for i := 0; i < length-1; i++ {
        fmt.Printf("\n第 %d 轮\n", i+1)

        // 假设当前未排序部分的第一个元素是最小值
        minIndex := i

        // 找到未排序部分的最小元素
        for j := i + 1; j < length; j++ {
            num++
            if arr[j] < arr[minIndex] {
                minIndex = j
            }
            fmt.Printf("第 %d 次比较\n", num)
        }

        fmt.Printf("此轮已排序序列:%v, ", arr[0:i])
        fmt.Printf("此轮未排序序列:%v, ", arr[i:length])

        // 将未排序部分的最小值与当前元素交换
        arr[i], arr[minIndex] = arr[minIndex], arr[i]
        fmt.Printf("此轮比较结果: %v\n", arr)
    }
}

func main() {
    arr := []int{5, 3, 8, 4, 2}
    selectionSort(arr)
    fmt.Println("\n排序结果: ", arr)
}

执行结果如下所示:

第 1 轮
第 1 次比较
第 2 次比较
第 3 次比较
第 4 次比较
此轮已排序序列:[], 此轮未排序序列:[5 3 8 4 2], 此轮比较结果: [2 3 8 4 5]

第 2 轮
第 5 次比较
第 6 次比较
第 7 次比较
此轮已排序序列:[2], 此轮未排序序列:[3 8 4 5], 此轮比较结果: [2 3 8 4 5]

第 3 轮
第 8 次比较
第 9 次比较
此轮已排序序列:[2 3], 此轮未排序序列:[8 4 5], 此轮比较结果: [2 3 4 8 5]

第 4 轮
第 10 次比较
此轮已排序序列:[2 3 4], 此轮未排序序列:[8 5], 此轮比较结果: [2 3 4 5 8]

排序结果:  [2 3 4 5 8]

实现选择排序,我们可以理解为:从数组的开始,先遍历一次找到最小的值,将最小的值拿出来,放在数组的头部arr[0],作为已排序序列,后面的都是未排序序列;下一次再继续从未排序序列找出最小的放到arr[1],以此类推。

总的来说,就是不断遍历获取最小值,那么未排序的数组就越来越小,直到最终全都遍历完成。

小结

本节我们讲解了选择排序的基本原理、步骤示例和 Go 语言的实现。

关于本节总结如下:

  • 时间复杂度:选择排序的时间复杂度为 O(n²),无论数组初始状态如何。

  • 稳定性:选择排序是不稳定的排序算法。

  • 应用场景:选择排序适合数据量较小或对排序效率要求不高的场景。

results matching ""

    No results matching ""